package org.common.utils.net.netty.http.listener;

import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.FullHttpRequest;
import org.common.utils.net.netty.http.core.HttpRequest;
import org.common.utils.net.netty.http.listener.entity.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * 监听器池
 * @author zhouzhibing
 * @date 2025/11/24 13:06
 */
public class HttpListenerPool {

    private static final Logger log = LoggerFactory.getLogger(HttpListenerPool.class);

    /**
     * 监听器列表
     */
    private final Map<HttpListener.Key, List<HttpListener<?>>> listenerMap = new ConcurrentHashMap<>();

    public HttpListenerPool() {
    }

    /**
     * channel激活时调用
     * @param ctx 上下文
     */
    public void channelActive(ChannelHandlerContext ctx) {
        dispatchListener(new ChannelActiveListenerInfo(ctx));
    }

    /**
     * 处理最开始，读取请求时的调用
     * @param request 请求
     * @return false处理不成功，表示被拦截，是否继续向下执行。
     */
    public void channelReadStart(ChannelHandlerContext ctx, FullHttpRequest request) {
        dispatchListener(new ChannelReadStartListenerInfo(ctx, request));
    }

    /**
     * 功能调用前。
     * @param request 请求
     * @return false处理不成功，表示被拦截，是否继续向下执行。
     */
    public void handlerRequestBefore(HttpRequest request) {
        dispatchListener(new HandlerRequestBeforeListenerInfo(request));
    }

    /**
     * 功能调用后。
     * @param request 请求
     * @param result 结果
     */
    public void handlerRequestAfter(HttpRequest request, Object result) {
        dispatchListener(new HandlerRequestAfterListenerInfo(request , result));
    }

    /**
     * 功能调用异常。
     * @param request 请求
     * @param e 异常
     */
    public void handlerException(HttpRequest request, Exception e) {
        dispatchListener(new HandlerExceptionListenerInfo(request , e));
    }

    /**
     * channel异常时调用
     * @param ctx 上下文
     * @param e 异常
     */
    public void channelException(ChannelHandlerContext ctx, Throwable e) {
        dispatchListener(new ChannelExceptionListenerInfo(ctx , e));
    }

    /**
     * channel注销时调用
     * @param ctx 上下文
     */
    public void channelUnregistered(ChannelHandlerContext ctx) {
        dispatchListener(new ChannelUnregisteredListenerInfo(ctx));
    }

    /**
     * 添加监听器
     * @param batch 批量监听器
     */
    public void addListener(HttpListener.Batch batch) {
        List<HttpListener<?>> listeners = batch.getListeners();
        for (HttpListener<?> listener : listeners) {
            addListener(listener);
        }
    }

    /**
     * 添加监听器
     * @param listener 监听器
     */
    public void addListener(HttpListener<?> listener) {
        Objects.requireNonNull(listener.getKey());
        Objects.requireNonNull(listener);
        List<HttpListener<?>> listeners = listenerMap.get(listener.getKey());
        if (listeners == null) {
            synchronized (this) {
                listeners = listenerMap.get(listener.getKey());
                if(listeners == null) {
                    listeners = new CopyOnWriteArrayList<>();
                    listenerMap.put(listener.getKey(), listeners);
                }
            }
        }
        listeners.add(listener);
    }

    /**
     * 添加监听器
     * @param listener 监听器
     */
    public void removeInterceptor(HttpListener<?> listener) {
        Objects.requireNonNull(listener.getKey());
        Objects.requireNonNull(listener);
        List<HttpListener<?>> listeners = listenerMap.get(listener.getKey());
        if (listeners == null) {
            return;
        }

        listeners.remove(listener);
    }

    /**
     * 执行监听器
     * @param info 监听器信息
     */
    private void dispatchListener(ListenerInfo info) {
        List<HttpListener<?>> listeners = listenerMap.get(info.getKey());
        if (listeners == null || listeners.isEmpty()) {
            return;
        }

        for (HttpListener<? extends ListenerInfo> listener : listeners) {
            try {
                ((HttpListener<ListenerInfo>) listener).doListener(info);
            } catch (Exception e) {
                log.error("dispatchListener error info = {}" , info , e);
            }
        }
    }


}
